package com.hgts.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import cn.hutool.core.lang.UUID;
import cn.hutool.core.util.RandomUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.hgts.common.R;
import com.hgts.mapper.LikesMapper;
import com.hgts.pojo.Likes;
import com.hgts.pojo.User;
import com.hgts.mapper.UserMapper;
import com.hgts.pojo.dto.UserDto;
import com.hgts.service.IUserService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hgts.utils.RegexUtils;
import com.hgts.utils.UserHolder;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.concurrent.TimeUnit;

import static com.hgts.utils.RedisConstants.*;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author 凡哥哥
 * @since 2023-05-09
 */
@Slf4j
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {
    @Autowired
    private StringRedisTemplate stringRedisTemplate;
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private LikesMapper likesMapper;
    @Override
    public R<User> login(User user) {
        //1.根据用户名查询数据库用户信息
        String username = user.getUsername();
        String phone = user.getPhone();
        String password = user.getPassword();
        //条件构造器
        LambdaQueryWrapper<User> lqw1 = new LambdaQueryWrapper();
        lqw1.and(q -> q.eq(User::getUsername, username).eq(User::getPassword,password))
                .or(q -> q.eq(User::getPhone, phone).eq(User::getPassword,password));
        User user1 = getOne(lqw1);
        //2.判断用户是否存在
        if (user1 == null) {
            //3.不存在，则返回错误信息
            return R.error("账号或密码错误");
        }
        //4.存在，随机生成token，作为登陆令牌
        String token = UUID.randomUUID().toString(true);
        //5.将User对象转换为HashMap存储到Redis中
        UserDto userDto = BeanUtil.copyProperties(user1,UserDto.class);
        Map<String, Object> userMap = BeanUtil.beanToMap(userDto,new HashMap<>(),
                CopyOptions.create()
                        .setIgnoreNullValue(true)
                        .setFieldValueEditor((fieldName,fieldValue) -> fieldValue.toString()));
        log.info("userMap:{}",userMap);
        String key = LOGIN_USER_KEY + token;
        stringRedisTemplate.opsForHash().putAll(key,userMap);
        //6.设置token有效期
        stringRedisTemplate.expire(key,LOGIN_USER_TTL, TimeUnit.MINUTES);
        //返回token
        return R.success(user1,token);
    }

    /*
    * 获取验证码
    * */
    @Override
    public R<String> sendCode(String phone) {
        //3.从缓存中校验手机号是否存在,存在就直接返回错误信息
        if(stringRedisTemplate.opsForSet().isMember(REGISTER_PHONE_KEY, phone)){
            return R.error("手机号已注册");
        }
        //4.不存在,则手机号注册用户,生成验证码
        String code = RandomUtil.randomNumbers(6);
        //5.将验证码存入Redis中
        stringRedisTemplate.opsForValue().set(LOGIN_CODE_KEY + phone,code,LOGIN_CODE_TTL, TimeUnit.MINUTES);
        //6.给用户发送验证码
        return R.success(code);
    }

    @Override
    public void exit(String token) {
        String key = LOGIN_USER_KEY + token;
        stringRedisTemplate.delete(key);
    }

    @Override
    public R<String> register(User user) {
        //校验手机号
        if(stringRedisTemplate.opsForSet().isMember(REGISTER_PHONE_KEY, user.getPhone())){
            return R.error("手机号已注册");
        }
        //从Redis中取出验证码,校验用户输入的验证码是否一致

        Optional<String> codeOptional = Optional.ofNullable(stringRedisTemplate.opsForValue().get(LOGIN_CODE_KEY + user.getPhone()));
        String code = codeOptional.orElse("null");
        String code1 = user.getCode();
        if (!code.equals(code1)){
            //不一致,返回验证码错误
            return R.error("验证码错误");
        }
        //一致,保存用户
        User user1 = new User();
        user1.setPhone(user.getPhone());
        user1.setPassword(user.getPassword());
        this.save(user1);
        //存储手机号到Redis,用于校验是否已注册过
        stringRedisTemplate.opsForSet().add(REGISTER_PHONE_KEY, user.getPhone());
        return R.success("注册成功");
    }

    @Override
    public List<Likes> likes(Long userId) {
        LambdaQueryWrapper<Likes> lqw = new LambdaQueryWrapper();
        lqw.eq(Likes::getUserId,userId);
        return likesMapper.selectList(lqw);
    }




}
